#include "central.h"

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>

using namespace std;

int TubeServeurVersClient[2];

Central::Central() {
	for (int index=10000; index<10020; index++) {
		this->PortsCommunication[index]=false;
	}
	int port = 12345;
	pthread_t serv;
	if (pthread_create(&serv,NULL, &thServeur,(void *) port) != 0)
	{
		cout << "C++ >> Central : echec etablir connexion" << endl;
		port = 99999;
	}
}

Central* Central::getInstance() {
	if (single == NULL) {
		single = new Central();
	}
	return single;
}

Central::~Central() {
}

//Initialisation du singleton
Central* Central::single = NULL;

//services
void* Central::envoyerAuClient(void* arg){
	
	char* mess = (char*) arg;
	cout<< "C++ >> Le thread Client ! " <<endl;
	
	close(TubeServeurVersClient[1]);
	while(read(TubeServeurVersClient[0],&mess,sizeof(mess))){
		cout <<"C++ >> Le message dit : " << &mess <<endl;	
	}
	close(TubeServeurVersClient[0]);
	return 0;
}

void* Central::envoyerAuServeur(void* arg){
	cout<< "C++ >> Le thread Serveur ! " <<endl;
	
	char* mess = (char*) arg;
	if(pipe(&TubeServeurVersClient[0]) == -1){
		cout <<"C++ >> La creation du tube ServeurVersClient a echoue" <<endl;
		exit(99);
	}
	close(TubeServeurVersClient[0]);
	write(TubeServeurVersClient[1],mess,sizeof(mess));
	close(TubeServeurVersClient[1]);
	return 0;
}

void* Central::thServeur(void * args)
{
	cout << "Serveur >> Initialisation du serveur" << endl;
	int  port = (int ) args;
	int sock ;
	struct hostent *hp;
	
	cout << port << endl;
	struct sockaddr_in adrServ;
	struct sockaddr_in adrClient;
      
	/* creation du socket */
        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		cout << "Serveur >> Echec de creation de la socket" << endl;
		pthread_exit(NULL);
	}

	adrServ.sin_family = AF_INET;
	adrServ.sin_addr.s_addr = htonl(INADDR_ANY);
	adrServ.sin_port = htons(port);

	if (bind(sock,(struct sockaddr *) &adrServ, sizeof(adrServ)) < 0)
	{
		cout << "Serveur >> Echec bind de la socket" << endl;
		pthread_exit(NULL);
	}

	listen(sock,5);

	cout << "C++ >> Serveur en attente" << endl;
	while (1)
	{
		/********** probleme ici *******/
		int uneSocket = accept(sock,(struct sockaddr*)&hp,(socklen_t*)sizeof(hp));		
		cout << "Serveur >> Un client est connecte" << endl;		
		
		pthread_t serv;
		cout<<"serveur sock"<< uneSocket<<endl;
		if (pthread_create(&serv,NULL, &thFils,(void *) uneSocket) != 0)
		{
			cout << "Serveur >> Echec creation thread fils" << endl;
		}	

		cout << "Serveur >>  Serveur disponible" << endl;
	}
	pthread_exit(NULL);
}

void * Central::thFils(void * args)
{
	int sock=(int) args;
	char * buf;
	struct sockaddr_in adrServ;
	struct hostent *hp;
	cout<< "C++ >> thread fils"<<endl;
	cout << "fils sock"<<sock <<endl;
	if(connect(sock,(struct sockaddr*)&hp,(socklen_t)sizeof(hp))==-1)
	{
		cout << "C++ >> Erreur connexion au socket" << endl;	
		pthread_exit(NULL);
	}
	recv(sock,&buf,255,0);
	cout<< "C++ >> Reception d'un message : " << buf <<endl;
}

int Central::etablir_connexion() {
	/*
	int port=99999;
	int res1,res2;
	bool test=false;
	
	
	map<int,bool>::iterator it;
	for (it=PortsCommunication.begin(); it != PortsCommunication.end() || !test; it++) {	
		if ((*it).second == false) {
			(*it).second = true;
			port = (*it).first;
			test=true;
		}
	}
		
	if(!test)
	{
		cout << "C++ >> Il n'y a plus aucun port de communication disponible "<< endl;
	}
	else
	{
		if( (res1=pthread_create(&client,NULL,envoyerAuServeur,(void*) port) != 0) 
		    || (res2=pthread_create(&serveur,NULL,envoyerAuClient,(void*)port) != 0 )){
			cout << "C++ >> Echec create_thread : res1 :"<< res1<<" - res2 : "<< res2 <<endl;	
		   }
	}

	return port;
	*/
	return 12345;
}

void Central::liberer_connexion(int numero_port)
{
	PortsCommunication[numero_port] = false;
}

